package org.hardcode.rpc.provider.common.server.base;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.sctp.nio.NioSctpServerChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.internal.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.hardcode.rpc.codec.RpcDecoder;
import org.hardcode.rpc.codec.RpcEncoder;
import org.hardcode.rpc.provider.common.handler.RpcProviderHandler;
import org.hardcode.rpc.provider.common.server.api.Server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * rpc框架服务提供者启动时通用功能封装在BaseServer中，由BaseServer类直接实现Server接口，
 * 并实现了接口中的startNettyServer()方法 在创建 一个RpcSingleServer类，继承BaseServer类
 */
public class BaseServer implements Server {

    private final Logger logger = LoggerFactory.getLogger(BaseServer.class);
    //主机域名或者ip
    protected String host = "127.0.0.1";
    //端口号
    protected int port = 27110;

    //存储实体关系
    protected Map<String, Object> handlerMap = new HashMap<>();

    public BaseServer(String serverAddress) {
        if (!StringUtils.isEmpty(serverAddress)) {
            String[] serverArray = serverAddress.split(":");
            this.host = serverArray[0];
            this.port = Integer.parseInt(serverArray[1]);
        }
    }

    /**
     * 如果需要再项目中使用Netty,可按照 startNettyServer中的代码示例启动Netty服务，
     * 启动Netty服务的代码是经典的代码模版
     */
    @Override
    public void startNettyServer() {

        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {

                            socketChannel.pipeline()
                                    //预留编解码 需要实现自定义协议
                                    //使用netty自带的StringEncoder和 StringDeconder
//                                    .addLast(new StringDecoder())
//                                    .addLast(new StringEncoder())
                                    //增加编解码的自定义方式
                                    .addLast(new RpcDecoder())
                                    .addLast(new RpcEncoder())
                                    //并将 RpcProviderHandler对象添加到Netty的数据传递链中 这样 RpcProviderHandler就可以接收外部传递的参数了

                                    .addLast(new RpcProviderHandler(handlerMap));
                        }
                    }).option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);


            ChannelFuture future = bootstrap.bind(host, port).sync();
            logger.info("Server started on  {}:{}",host,port);
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            logger.error("RPC Server start error ",e);
        }finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }


}
